package com.zatech.cgnci.project.base.utils;

import com.alibaba.fastjson.JSONArray;
import com.zatech.cgnci.project.dto.AreaDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.ClassPathResource;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author EDY
 * @version 1.0
 * Create by 2024/12/18 14:20
 */
public class AreaUtils {

    private static Map<String, List<AreaDTO>> AREA_CACHE = new HashMap<>(3);

    /**
     * <p>@Description: getProvinceList 获取省级列表</P>
     * <pre>
     *  AreaUtil.getProvinceList(null) =查询所有
     *  AreaUtil.getProvinceList("110000") =查询所有
     * </pre>
     */
    public static List<AreaDTO> getProvinceList(String id) {
        return getList(0, id);
    }

    /**
     * <p>@Description: getCityList 获取市级列表.</P>
     * <pre>
     *  AreaUtil.getCityList(null) =返回空数组 :[]
     *  AreaUtil.getCityList("110000") =查询所有该省下所有的市列表
     * </pre>
     */
    public static List<AreaDTO> getCityList(String lastId) {

        if (StringUtils.isEmpty(lastId)) {
            return new ArrayList<>();
        }
        return getList(1, lastId);

    }

    /**
     * <p>@Description: getDistrictList 获取市级下所有区列表</P>
     * <pre>
     *  AreaUtil.getDistrictList(null) =返回空数组 :[]
     *  AreaUtil.getDistrictList("110100") =查询所有该市级下所有的区列表
     * </pre>
     */
    public static List<AreaDTO> getDistrictList(String lastId) {

        if (StringUtils.isEmpty(lastId)) {
            return new ArrayList<>();
        }
        return getList(2, lastId);
    }

    /**
     * <pre>
     * AreaUtil.getList(0,null)         =查询所有省列表
     * AreaUtil.getList(0,"110000")      =查询所有省列表
     * AreaUtil.getList(1,"110000")      =查询某省下所有市级列表
     * AreaUtil.getList(1,null)      =返回空数组
     * AreaUtil.getList(2,"110100")      =返回某市下所有区列表
     * AreaUtil.getList(2,null)      =返回空数组
     * </pre>
     *
     * @param type   0=查询所有列表,1=查询省下所有市,2=市下所有区
     * @param lastId 上一级id
     */
    public static List<AreaDTO> getList(Integer type, String lastId) {
        try {
            String key = type.toString() + lastId;
            List<AreaDTO> areaDtos = AREA_CACHE.get(key);
            if (VerifyUtils.isNotEmpty(areaDtos)) {
                return areaDtos;
            }
            String path = "/file/";
            if (type == 0) {
                path = path + "province.json";
            } else if (type == 1) {
                path = path + "city.json";
            } else if (type == 2) {
                path = path + "district.json";
            }

            ClassPathResource resource = new ClassPathResource(path);
            InputStream inputStream = resource.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder builder = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                builder.append(line);
            }
            br.close();
            List<AreaDTO> dtos = JSONArray.parseArray(builder.toString(), AreaDTO.class);
            if (type == 0) {
                return dtos;
            }
            List<AreaDTO> outDto = new ArrayList<>();
            if (StringUtils.isEmpty(lastId)) {
                return dtos;
            }
            dtos.forEach(item -> {
                if (item.getFatherId().equals(lastId)) {
                    outDto.add(item);
                }
            });
            AREA_CACHE.put(key, outDto);
            return outDto;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    public static String getNameById(String id) {

        StringBuilder buffer = new StringBuilder();
        try {
            if (StringUtils.isEmpty(id)) {
                throw new Exception();
            }
            AtomicInteger atomicInteger = new AtomicInteger(0);
            while (atomicInteger.get() < 3) {
                List<AreaDTO> list = getList(atomicInteger.get(), null);
                for (AreaDTO item : list) {
                    if (item.getCode().equals(id)) {
                        buffer.append(item.getName());
                        atomicInteger.set(4);
                        break;
                    }
                }
                atomicInteger.incrementAndGet();
            }

            return buffer.toString();
        } catch (Exception e) {
            return "";
        }
    }

    public static AreaDTO getByLabel(Integer type, String label) {

        if (type == null || StringUtils.isEmpty(label)) {
            return null;
        }
        List<AreaDTO> list = getList(type, null);
        if (VerifyUtils.isEmpty(list)) {
            return null;
        }
        for (AreaDTO item : list) {
            if (item.getName().equals(label)) {
                return item;
            }
        }
        return null;
    }

    public static AreaDTO getByValue(Integer type, String value) {

        if (type == null || StringUtils.isEmpty(value)) {
            return null;
        }
        List<AreaDTO> list = getList(type, null);
        if (VerifyUtils.isEmpty(list)) {
            return null;
        }
        for (AreaDTO item : list) {
            if (item.getCode().equals(value)) {
                return item;
            }
        }
        return null;
    }

    /**
     * 获取指定城市下的指定区域
     * @param cityLabel 城市名
     * @param areaLabel 区域名
     * @return
     */
    @Deprecated
    public static Optional<AreaDTO> getByCityLabelAndAreaLabel(String cityLabel, String areaLabel) {

        if (StringUtils.isEmpty(cityLabel) || StringUtils.isEmpty(areaLabel)) {
            return Optional.empty();
        }
        AreaDTO cityAreaDto = getByLabel(1, cityLabel);
        if (cityAreaDto == null) {
            return Optional.empty();
        }
        List<AreaDTO> list = AreaUtils.getList(2, cityAreaDto.getName());
        if (VerifyUtils.isEmpty(list)) {
            return Optional.empty();
        }
        for (AreaDTO areaDto : list) {
            if (areaDto.getCode().equals(areaLabel)) {
                return Optional.of(areaDto);
            }
        }
        return Optional.empty();
    }
}
